﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using CommonPay.WePay.AppPay;
using CommonPay.WePay.XcxPay;
using HttpLib.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Payment.API.Application.Services;
using Payment.API.ViewModel;

namespace Payment.API.Controllers.Pay
{
    [Route("api/v1/[controller]")]
    [ApiController]
    public class WeChatAppPayController : BaseController
    {
        private readonly ILogger<WeChatAppPayController> _logger;
        private readonly IIdentityService _identityService;
        private readonly PaymentSettings _settings;
        private readonly IAppPayApi _appPayApi;
        private IHttpContextAccessor _context;
        private IPaymentService _paymentService;
        public WeChatAppPayController(ILogger<WeChatAppPayController> logger,
            IIdentityService identityService,
            IOptionsSnapshot<PaymentSettings> settings,
            IHttpContextAccessor context,
            IAppPayApi appPayApi,
            IPaymentService paymentService)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
            _settings = settings.Value ?? throw new ArgumentNullException(nameof(settings));
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _appPayApi = appPayApi ?? throw new ArgumentNullException(nameof(appPayApi));
            _paymentService = paymentService ?? throw new ArgumentNullException(nameof(paymentService));
        }
        /// <summary>
        /// 微信app支付
        /// </summary>
        /// <param name="request"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("apppay")]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<ActionResult> WxPayAppAsync([FromBody] WeChatAppPayRequest request, [FromHeader(Name = "x-requestid")] string requestId)
        {
            if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty)
            {
                var userId = _identityService.GetUserIdentity();
                // App调用只能传参
                #region 验证订单是否有效

                decimal payPrice = 0;
                string detail = "";

                /// 验证订单是否有效，并统计订单总金额

                #endregion

                #region 统一下单
                try
                {
                    //string userId = LoginUser.Id.ToString();
                    var address = _settings.WxAppNotifyUrl;
                    AppPayData data = new AppPayData();
                    data.SetValue("body", "");
                    data.SetValue("attach", String.Join(",", request.OrderIds).ToString());
                    Random rd = new Random();
                    var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0');
                    data.SetValue("out_trade_no", payNum);
                    data.SetValue("detail", detail.Substring(0, detail.Length - 1));
                    data.SetValue("total_fee", Convert.ToInt32(payPrice * 100));
                    data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                    data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                    data.SetValue("notify_url", address);

                    //注意，这里交易方式是APP
                    data.SetValue("trade_type", "APP");

                    AppPayData result = await _appPayApi.UnifiedOrderAsync(data);
                    var appid = "";
                    var partnerid = "";
                    var prepayid = "";
                    var package = "";
                    var nonceStr = "";
                    var timestamp = "";
                    var sign = "";
                    if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
                    {
                        return BadRequest(new { result = false, message = "下单失败！" });
                    }
                    else
                    {
                        //统一下单
                        List<string> payOrderIds = new List<string>();
                        request.OrderIds.ForEach(t =>
                        {
                            payOrderIds.Add(t.ToString());
                        });
                        //修改订单状态
                        await _paymentService.PaySucceededAsync(payOrderIds, userId);

                        appid = result.GetValue("appid").ToString();
                        nonceStr = result.GetValue("nonce_str").ToString();
                        partnerid = result.GetValue("mch_id").ToString();
                        prepayid = result.GetValue("prepay_id").ToString();
                        package = "Sign=WXPay";// "prepay_id=" + result.GetValue("prepay_id").ToString();
                    }
                    var signType = "MD5";
                    timestamp = ((DateTime.Now.Ticks - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).Ticks) / 10000).ToString();
                    AppPayData applet = new AppPayData();
                    applet.SetValue("appid", appid);
                    applet.SetValue("noncestr", nonceStr);
                    applet.SetValue("package", package);
                    applet.SetValue("partnerid", partnerid);
                    applet.SetValue("prepayid", prepayid);
                    //applet.SetValue("signType", signType);
                    applet.SetValue("timestamp", timestamp);
                    sign = applet.MakeSign();
                    return Ok(new { appid, partnerid, prepayid, package, nonceStr, timestamp, sign });
                }
                catch (Exception ex)
                {
                    return BadRequest(new { result = false, message = "缺少参数！" });
                }

                #endregion
            }
            else
            {
                return BadRequest();
            }
        }

        /// <summary>
        /// 微信支付回调
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("appnotify")]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> WxAppNotifyUrlAsync()
        {
            _logger.LogInformation("WxAppNotifyUrl", "支付回调");
            AppPayData notifyData = await _appPayApi.GetNotifyDataAsync();

            //检查支付结果中transaction_id是否存在
            if (!notifyData.IsSet("transaction_id"))
            {
                //若transaction_id不存在，则立即返回结果给微信支付后台
                AppPayData res = new AppPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "支付结果中微信订单号不存在");
                _logger.LogError(this.GetType().ToString(), "The Pay result is error : " + res.ToXml());
                return BadRequest(res.ToXml());
            }

            string transaction_id = notifyData.GetValue("transaction_id").ToString();

            //查询订单，判断订单真实性
            if (!await AppQueryOrder(transaction_id))
            {
                //若订单查询失败，则立即返回结果给微信支付后台
                AppPayData res = new AppPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "订单查询失败");
                _logger.LogError(this.GetType().ToString(), "Order query failure : " + res.ToXml());
                return BadRequest(res.ToXml());
            }
            //查询订单成功
            else
            {
                AppPayData res = new AppPayData();
                res.SetValue("return_code", "SUCCESS");
                res.SetValue("return_msg", "OK");
                _logger.LogInformation(this.GetType().ToString(), "Order query success : " + res.ToXml());
                _logger.LogInformation(this.GetType().ToString(), "Order query success,notifyData : " + notifyData.ToXml());
                var returnCode = notifyData.GetValue("return_code").ToString();
                var transactionNo = transaction_id;//微信订单号
                var outTradeNo = notifyData.GetValue("out_trade_no").ToString();//自定义订单号
                var attach = notifyData.GetValue("attach").ToString();//身份证
                var endTime = notifyData.GetValue("time_end").ToString();//交易结束时间
                //var body = notifyData.GetValue("body").ToString();//projectIdlist
                var totalFee = notifyData.GetValue("total_fee").ToString(); ;//支付金额

                int userId = Convert.ToInt32(attach.Split('|')[0]);
                string msg;
                try
                {
                    ///修改数据库订单状态
                    //var result = OrderBll.Value.CompleteWePay(userId, totalFee, transactionNo, returnCode, outTradeNo, attach, endTime, out msg);
                    var result = true;

                    _logger.LogInformation(this.GetType().ToString(), "CompleteWePay:" + result);
                }
                catch (Exception e)
                {
                    _logger.LogInformation(this.GetType().ToString(), "CompleteWePay:" + e.ToString());
                }

                return Ok(res.ToXml());
            }
        }
        /// <summary>
        /// 查询订单
        /// </summary>
        /// <param name="transaction_id"></param>
        /// <returns></returns>
        private async Task<bool> AppQueryOrder(string transaction_id)
        {
            AppPayData req = new AppPayData();
            req.SetValue("transaction_id", transaction_id);
            AppPayData res = await _appPayApi.OrderQueryAsync(req);
            if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
